#!/usr/bin/env python3
# Copyright (C) 2017 Florian Festi
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program.  If not, see <http://www.gnu.org/licenses/>.

import argparse
import os.path
import sys
from xml.sax.saxutils import quoteattr

try:
    import boxes.generators
except ImportError:
    sys.path.append(os.path.dirname(__file__) + "/..")
    import boxes.generators


class Boxes2INX:
    def __init__(self) -> None:
        self.boxes = {b.__name__: b() for b in boxes.generators.getAllBoxGenerators().values() if b.webinterface}
        self.groups = boxes.generators.ui_groups
        self.groups_by_name = boxes.generators.ui_groups_by_name

        for name, box in self.boxes.items():
            self.groups_by_name.get(box.ui_group,
                                    self.groups_by_name["Misc"]).add(box)

    def arg2inx(self, a, prefix):
        name = a.option_strings[0].replace("-", "")

        if isinstance(a, argparse._HelpAction):
            return ""

        viewname = name
        if prefix and name.startswith(prefix + '_'):
            viewname = name[len(prefix) + 1:]

        if (isinstance(a, argparse._StoreAction) and hasattr(a.type, "inx")):
            return a.type.inx(name, viewname, a)  # see boxes.__init__.py
        elif a.dest == "layout":
            return ""
            val = a.default.split("\n")
            input = """<textarea name="%s" cols="%s" rows="%s">%s</textarea>""" % \
                    (name, max(len(l) for l in val) + 10, len(val) + 1, a.default)
        elif a.choices:
            uniqueChoices = []
            for e in a.choices:
                if e not in uniqueChoices:
                    uniqueChoices.append(e)
            return ('''        <param name="%s" type="optiongroup" appearance="combo" gui-text="%s" gui-description=%s>\n'''
                    % (name, viewname, quoteattr(a.help or viewname)) +
                    "".join('            <option value="%s">%s</option>\n' % (e, e) for e in uniqueChoices) + '    </param>\n')
        else:
            default = a.default
            if isinstance(a.type, boxes.BoolArg):
                t = '"bool"'
                default = str(a.default).lower()

            elif a.type is boxes.argparseSections:
                t = '"string"'

            else:
                t = {int: '"int"',
                     float: '"float" precision="2"',
                     str: '"string"',
                     }.get(a.type, '"string"')

            if t == '"int"' or t == '"float" precision="2"':
                return '''        <param name="%s" type=%s max="9999" gui-text="%s" gui-description=%s>%s</param>\n''' % (name, t, viewname, quoteattr(a.help or viewname), default)

            else:
                return '''        <param name="%s" type=%s gui-text="%s" gui-description=%s>%s</param>\n''' % (name, t, viewname, quoteattr(a.help or viewname), default)

    def generator2inx(self, name, box):
        result = ["""<?xml version="1.0" encoding="UTF-8"?>
<inkscape-extension xmlns="http://www.inkscape.org/namespace/inkscape/extension">
<name>%s</name>
<id>info.festi.boxes.py.%s</id>
<param name="generator" type="string" gui-hidden="true">%s</param>
<param name="tab" type="notebook">""" % (name, name, name.lower())]
        groupid = 0
        for group in box.argparser._action_groups:
            if not group._group_actions:
                continue
            prefix = getattr(group, "prefix", None)
            title = group.title
            if title.startswith("Settings for "):
                title = title[len("Settings for "):]
            if title.endswith(" Settings"):
                title = title[:-len(" Settings")]

            pageParams = []
            for a in group._group_actions:
                if a.dest in ("input", "output", "format"):
                    continue
                if self.arg2inx(a, prefix) != "":
                    pageParams.append(self.arg2inx(a, prefix))
            if len(pageParams) > 0:
                result.append("""
    <page name="tab_%s" gui-text="%s">
""" % (groupid, title))
                result.extend(pageParams)
                result.append("    </page>")

            groupid += 1
        result.append("""
    <page name="tab_%s" gui-text="Example">
""" % (groupid))
        result.append("        <image>./" + name + "-thumb.jpg</image>\n")
        result.append("    </page>\n")
        result.append("""</param>
<label appearance="url">https://www.festi.info/boxes.py/""" + name + """</label>
<effect>
    <object-type>all</object-type>
    <effects-menu>
        <submenu name="Boxes.py">
            <submenu name="%s"/>
        </submenu>
    </effects-menu>
</effect>
<script>
    <command location="inx" interpreter="python">boxes_proxy.py</command>
</script>
</inkscape-extension>""" % self.groups_by_name[box.ui_group].title)
        return b''.join(s.encode("utf-8") for s in result)

    def writeINX(self, name, box, path):
        with open(os.path.join(path, "boxes.py." + name + '.inx'), "wb") as f:
            f.write(self.generator2inx(name, box))

    def writeAllINX(self, path):
        for name, box in self.boxes.items():
            if name.startswith("TrayLayout"):
                # The two stage thing does not work (yet?)
                continue
            self.writeINX(name, box, path)


def main() -> None:
    if len(sys.argv) != 2:
        print("Usage: boxes2inkscape TARGETPATH")
        return
    b = Boxes2INX()
    b.writeAllINX(sys.argv[1])


if __name__ == "__main__":
    main()
